package com.hzw.saas.web.app.group.controller;


import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.hzw.saas.api.group.IGroupMemberRoleRefService;
import com.hzw.saas.api.group.IGroupMemberService;
import com.hzw.saas.api.group.IGroupService;
import com.hzw.saas.api.group.bo.GroupBo;
import com.hzw.saas.api.group.bo.UserMemberBo;
import com.hzw.saas.api.group.query.GroupMemberRoleQuery;
import com.hzw.saas.api.group.query.GroupMsgQuery;
import com.hzw.saas.api.group.query.UserInviteQuery;
import com.hzw.saas.api.user.ICustomerRefService;
import com.hzw.saas.api.user.ICustomerService;
import com.hzw.saas.api.user.IStaffService;
import com.hzw.saas.api.user.IUserAccountService;
import com.hzw.saas.api.user.bo.CustomerRefBO;
import com.hzw.saas.api.user.bo.StaffBO;
import com.hzw.saas.api.user.bo.UserAccountBO;
import com.hzw.saas.api.user.export.UserRegisterBO;
import com.hzw.saas.common.config.annotation.SysLog;
import com.hzw.saas.common.config.util.AssertUtil;
import com.hzw.saas.common.config.util.PageParam;
import com.hzw.saas.common.config.util.PageUtils;
import com.hzw.saas.common.security.pojo.dto.SaasUser;
import com.hzw.saas.common.security.utils.SecurityUtils;
import com.hzw.saas.web.app.group.annotation.GroupOperation;
import com.hzw.saas.web.app.group.annotation.MemberOperation;
import com.hzw.saas.web.app.group.dto.UserMemberDTO;
import com.hzw.saas.web.app.group.param.GroupInviteParam;
import io.swagger.annotations.*;
import jodd.util.StringUtil;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 用户组成员表 前端控制器
 * </p>
 *
 * @author sonam
 * @since 2020-12-23
 */
@RestController
@AllArgsConstructor
@Slf4j
@Api(tags = "群组管理/群组成员")
public class GroupMemberController {

    private final IStaffService staffService;
    private final IGroupService groupService;
    private final IGroupMemberService groupMemberService;
    private final IGroupMemberRoleRefService memberRoleRefService;
    private final ICustomerRefService customerRefService;
    private final IUserAccountService userAccountService;

    @Resource
    private ICustomerService customerService;

    @GetMapping("/group/members/{groupId}")
    @ApiOperation(value = "获取群组成员列表", notes = "获取某个群组的所有成员列表，包括权限信息")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "groupId", value = "群组ID", required = true)
    })
    @ApiOperationSort(1)
    public ResponseEntity<IPage<UserMemberDTO>> getUserGroup(@PathVariable String groupId, PageParam pageParam) {
        IPage<UserMemberBo> userRoleDtoList = groupMemberService.getGroupUserAndRoleList(groupId, pageParam.convert());

        // 临时
        GroupBo groupBo = groupService.getGroupById(groupId);
        if (groupBo != null && StringUtil.isBlank(groupBo.getOwnerId()) && (pageParam == null || pageParam.getCurrent() == 1)) {
            List<UserMemberBo> records = userRoleDtoList.getRecords();
            if (CollectionUtils.isEmpty(records)) {
                userRoleDtoList.setRecords(new ArrayList<>());
            }
            String userId = SecurityUtils.getUser().getUserId();
            List<CustomerRefBO> customerRefBOS = customerRefService.search(new CustomerRefBO().setUserId(userId));
            if (CollectionUtils.isNotEmpty(customerRefBOS)) {
                SaasUser user = SecurityUtils.getUser();
                Optional<UserAccountBO> account = Optional.ofNullable(userAccountService.getAccount(user.getUserId()));
                userRoleDtoList.getRecords().add(new UserMemberBo()
                    .setUserId(userId)
                    .setJoinDate(new Date())
                    .setMemberId("1")
                    .setRoleId("2")
                    .setUsername(user.getUsername())
                    .setRoleName("成员")
                    .setPhoneNo(account.map(UserAccountBO::getPhoneNo).orElse(""))
                    .setEmail(account.map(UserAccountBO::getEmail).orElse("")));
                userRoleDtoList.setTotal(userRoleDtoList.getTotal() + 1);
                customerRefBOS.forEach(customerRefBO -> {
                    String staffId = customerRefBO.getStaffId();
                    StaffBO staffBO = staffService.getById(staffId);
                    if (Objects.isNull(staffBO)) {
                        return;
                    }
                    userRoleDtoList.getRecords().add(0, new UserMemberBo()
                        .setUserId(staffId)
                        .setJoinDate(new Date())
                        .setMemberId("1")
                        .setRoleId("2")
                        .setUsername(staffBO.getStaffName())
                        .setRoleName("成员")
                        .setPhoneNo(staffBO.getStaffPhoneNo())
                        .setEmail(staffBO.getStaffEmail()));
                    userRoleDtoList.setTotal(userRoleDtoList.getTotal() + 1);
                });
            }
        }
        List<UserMemberBo> records = userRoleDtoList.getRecords();
        if (CollectionUtils.isNotEmpty(records)) {
            List<String> collect = records.stream().map(UserMemberBo::getUserId).collect(Collectors.toList());
            List<UserRegisterBO> byUserIds = customerService.findByUserIds(collect);
            IPage<UserMemberDTO> convert = PageUtils.convert(userRoleDtoList, UserMemberDTO.class);
            List<UserMemberDTO> dtoList = convert.getRecords();
            dtoList.forEach(userMemberDTO -> {
                byUserIds.forEach(userRegisterBO -> {
                    if (userMemberDTO.getUserId().equals(userRegisterBO.getUserId())) {
                        userMemberDTO.setCustomerName(userRegisterBO.getCustomerName());
                    }
                });
            });
            return ResponseEntity.ok(convert);
        }
        return ResponseEntity.ok(new Page<>());
    }

    @SysLog(operation = "移除群组中的成员")
    @GroupOperation(groupId = "#groupId", errorMsg = "处理失败，当前群组你没有权限")
    @DeleteMapping("/group/{groupId}/member/{memberId}")
    @ApiOperation(value = "移除群组中的成员", notes = "指定成员进行移除")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "groupId", value = "群组id", required = true),
        @ApiImplicitParam(name = "memberId", value = "成员id", required = true)
    })
    @ApiResponses({
        @ApiResponse(code = 200, message = "从群组里移除成员成")
    })
    @ApiOperationSort(2)
    public ResponseEntity<String> removeMemberByGroup(@PathVariable String groupId, @PathVariable String memberId) {
        /**
         * 1、移除群组中的成员（参数成员id与群组id）
         * 2、查询成员id的角色，如果为群组，则删除失败
         * 3、从成员表中，根据成员id和群组id，删除成员
         * 4、角色成员关联表，删除成员id对应的关联记录
         */
        groupService.removeMemberByGroup(groupId, memberId, SecurityUtils.getUser().getUserId());
        return ResponseEntity.ok("从群组里移除成员成功");
    }

    @SysLog(operation = "离开群组")
    @PostMapping("/group/leave/{groupId}")
    @ApiOperation(value = "离开群组", notes = "指定群组id，主动离开该群组")
    @ApiImplicitParams({
        @ApiImplicitParam(name = "groupId", value = "群组id-String", required = true)
    })
    @ApiResponses({
        @ApiResponse(code = 200, message = "离开群组成功")
    })
    @ApiOperationSort(3)
    public ResponseEntity<String> leaveGroup(@PathVariable String groupId) {
        /**
         * 1、查询当前用户是否在groupId的群组中
         * 2、当前用户不是群主则允许删除
         * 2、不存在则离开失败，存在则调用移除成员接口
         */
        groupService.leaveGroup(SecurityUtils.getUser().getUserId(), groupId);
        return ResponseEntity.ok("离开群组成功");
    }

    @SysLog(operation = "设置群组成员角色")
    @PutMapping("/group/member/role")
    @ApiOperation(value = "设置群组成员角色", notes = "设置群成员角色")
    @ApiResponses({
        @ApiResponse(code = 200, message = "设置角色成功", response = String.class)
    })
    @ApiOperationSort(4)
    @MemberOperation(memberId = "#memberRoleParam.memberId", error = "设置角色失败，你没有权限")
    public ResponseEntity<String> updateMemberRole(@Valid @RequestBody GroupMemberRoleQuery memberRoleParam) {
        // FIXME
        AssertUtil.assertThrow("设置角色失败，无法设置群主角色", Objects.equals(memberRoleParam.getRoleId(), "1"));
        memberRoleRefService.updateMemberRole(memberRoleParam.getMemberId(), memberRoleParam.getRoleId());
        return ResponseEntity.ok("设置角色成功");
    }

    @SysLog(operation = "申请加入群组")
    @PostMapping("/group/join/{groupId}")
    @ApiOperation(value = "申请加入群组")
    @ApiOperationSort(5)
    public ResponseEntity<String> requestJoinGroup(@ApiParam(value = "groupId") @PathVariable String groupId) {
        groupService.requestJoinGroup(SecurityUtils.getUser().getUserId(), groupId);
        return ResponseEntity.ok("发送申请加入群组信息成功");
    }

    @SysLog(operation = "群主(同意/拒绝)用户加入")
    @PutMapping("/group/invite/reply")
    @ApiOperation(value = "群主(同意/拒绝)用户加入", notes = "用户主动申请加入群组时,同意或者拒绝调用此接口")
    @ApiResponses({
        @ApiResponse(code = 200, message = "同意/拒绝操作成功")
    })
    @ApiOperationSort(6)
    public ResponseEntity<String> replyUser(@Valid @RequestBody GroupMsgQuery groupMsgParam) {
        String groupId = groupMsgParam.getGroupId();
        GroupBo groupBo = groupService.getGroupById(groupId);
        AssertUtil.assertThrow("确认用户加入/拒绝群组失败，不能操作当前群组", !Objects.equals(groupBo.getOwnerId(), SecurityUtils.getUser().getUserId()));
        String errorMsg = groupService.confirmMember(groupMsgParam);
        if (Objects.isNull(errorMsg)) {
            return ResponseEntity.ok("操作成功，群主(同意/拒绝)用户加入");
        } else {
            return ResponseEntity.badRequest().body(errorMsg);
        }
    }

    @SysLog(operation = "主动邀请用户加入群组")
    @PostMapping("/group/invite")
    @ApiOperation(value = "主动邀请用户加入群组", notes = "主动邀请成员加入群组")
    @ApiOperationSort(7)
    public ResponseEntity<String> inviteUser(@Validated @RequestBody GroupInviteParam groupInviteParam) {
        AssertUtil.assertThrow("邀请失败,你不能邀请自己", Objects.equals(groupInviteParam.getUserId(), SecurityUtils.getUser().getUserId()));

        String groupId = groupInviteParam.getGroupId();
        groupService.inviteUserJoinGroup(groupInviteParam.getUserId(), groupId);
        return ResponseEntity.ok("发送申请加入群组信息成功");
    }

    @SysLog(operation = "用户(同意/拒绝)加入群组")
    @PutMapping("/user/invite/reply")
    @ApiOperation(value = "用户(同意/拒绝)加入群组", notes = "用户确认群组邀请信息")
    @ApiOperationSort(8)
    public ResponseEntity<String> userInviteReply(@Validated @RequestBody UserInviteQuery userInviteParam) {
        AssertUtil.assertThrow("操作失败, 该操作参数异常", !Objects.equals(userInviteParam.getUserId(), SecurityUtils.getUser().getUserId()));
        String errorMsg = groupService.confirmGroup(userInviteParam);
        if (Objects.isNull(errorMsg)) {
            return ResponseEntity.ok("操作成功，用户(同意/拒绝)加入群组");
        } else {
            return ResponseEntity.badRequest().body(errorMsg);
        }
    }

}
